Completed
Push — 16.1 ( 7ccc73...046888 )
by Nathan
64:46 queued 51:15
created

AppJS.extend.insert_text   D

Complexity

Conditions 16
Paths 138

Size

Total Lines 76

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
nc 138
nop 2
dl 0
loc 76
rs 4.8771
c 0
b 0
f 0

5 Functions

Rating   Name   Duplication   Size   Complexity  
A AppJS.extend.toggleEncrypt 0 1 1
A AppJS.extend.onchangeResponsible 0 7 3
B AppJS.extend._get_stylite 0 24 2
A AppJS.extend._get_stylite 0 9 2
A AppJS.extend.toggleEncrypt 0 9 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like AppJS.extend.insert_text often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * EGroupware - Infolog - Javascript UI
3
 *
4
 * @link http://www.egroupware.org
5
 * @package infolog
6
 * @author Hadi Nategh	<hn-AT-stylite.de>
7
 * @copyright (c) 2008-13 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
8
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
9
 * @version $Id$
10
 */
11
12
/**
13
 * UI for Infolog
14
 *
15
 * @augments AppJS
16
 */
17
app.classes.infolog = AppJS.extend(
18
{
19
	appname: 'infolog',
20
21
	/**
22
	 * Constructor
23
	 *
24
	 * @memberOf app.infolog
25
	 */
26
	init: function()
27
	{
28
		// call parent
29
		this._super.apply(this, arguments);
30
	},
31
32
	/**
33
	 * Destructor
34
	 */
35
	destroy: function()
36
	{
37
		// call parent
38
		this._super.apply(this, arguments);
39
	},
40
41
	/**
42
	 * This function is called when the etemplate2 object is loaded
43
	 * and ready.  If you must store a reference to the et2 object,
44
	 * make sure to clean it up in destroy().
45
	 *
46
	 * @param {etemplate2} _et2 newly ready object
47
	 * @param {string} _name template name
48
	 */
49
	et2_ready: function(_et2, _name)
50
	{
51
		// call parent
52
		this._super.apply(this, arguments);
53
54
		switch(_name)
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
55
		{
56
			case 'infolog.index':
57
				this.filter_change();
58
				// Show / hide descriptions according to details filter
59
				var nm = this.et2.getWidgetById('nm');
60
				var filter2 = nm.getWidgetById('filter2');
61
				this.show_details(filter2.value == 'all',nm.getDOMNode(nm));
62
				// Remove the rule added by show_details() if the template is removed
63
				jQuery(_et2.DOMContainer).on('clear', jQuery.proxy(function() {egw.css(this);}, '#' + nm.getDOMNode(nm).id + ' .et2_box.infoDes'));
64
65
				// Enable decrypt on hover
66
				if(this.egw.user('apps').stylite)
67
				{
68
					this._get_stylite(function() {this.mailvelopeAvailable(function() {app.stylite.decrypt_hover(nm);});});
69
				}
70
				break;
71
			case 'infolog.edit.print':
72
				if (this.et2.getArrayMgr('content').data.info_des.indexOf(this.begin_pgp_message) != -1)
73
				{
74
					this.mailvelopeAvailable(this.printEncrypt);
75
				}
76
				else
77
				{
78
					// Trigger print command if the infolog oppend for printing purpose
79
					this.infolog_print_preview_onload();
80
				}
81
				break;
82
			case 'infolog.edit':
83
				if (this.et2.getArrayMgr('content').data.info_des &&
84
					this.et2.getArrayMgr('content').data.info_des.indexOf(this.begin_pgp_message) != -1)
85
				{
86
					this._get_stylite(jQuery.proxy(function() {this.mailvelopeAvailable(jQuery.proxy(function() {
87
						this.toggleEncrypt();
88
89
						// Decrypt history on hover
90
						var history = this.et2.getWidgetById('history');
91
						app.stylite.decrypt_hover(history,'span');
92
						jQuery(history.getDOMNode(history))
93
							.tooltip('option','position',{my:'top left', at: 'top left', of: history.getDOMNode(history)});
94
95
					},this));},this));
96
					// This disables the diff in history
97
					var history = this.et2.getArrayMgr('content').getEntry('history');
98
					history['status-widgets'].De = 'description';
99
				}
100
				break;
101
		}
102
	},
103
104
	/**
105
	 * Observer method receives update notifications from all applications
106
	 *
107
	 * InfoLog currently reacts to timesheet updates, as it might show time-sums.
108
	 * @todo only trigger update, if times are shown
109
	 *
110
	 * @param {string} _msg message (already translated) to show, eg. 'Entry deleted'
111
	 * @param {string} _app application name
112
	 * @param {(string|number)} _id id of entry to refresh or null
113
	 * @param {string} _type either 'update', 'edit', 'delete', 'add' or null
114
	 * - update: request just modified data from given rows.  Sorting is not considered,
115
	 *		so if the sort field is changed, the row will not be moved.
116
	 * - edit: rows changed, but sorting may be affected.  Requires full reload.
117
	 * - delete: just delete the given rows clientside (no server interaction neccessary)
118
	 * - add: requires full reload for proper sorting
119
	 * @param {string} _msg_type 'error', 'warning' or 'success' (default)
120
	 * @param {object|null} _links app => array of ids of linked entries
121
	 * or null, if not triggered on server-side, which adds that info
122
	 */
123
	observer: function(_msg, _app, _id, _type, _msg_type, _links)
124
	{
125
		if (typeof _links != 'undefined')
126
		{
127
			if (typeof _links.infolog != 'undefined')
128
			{
129
				switch (_app)
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
130
				{
131
					case 'timesheet':
132
						var nm = this.et2 ? this.et2.getWidgetById('nm') : null;
133
						if (nm) nm.applyFilters();
134
						break;
135
				}
136
			}
137
		}
138
		// Refresh handler for Addressbook CRM view
139
		if (_app == 'infolog' && this.et2.getInstanceManager() && this.et2.getInstanceManager().app == 'addressbook' && this.et2.getInstanceManager().name == 'infolog.index')
140
		{
141
			this.et2._inst.refresh(_msg, _app, _id, _type);
142
		}
143
	},
144
145
	/**
146
	 * Retrieve the current state of the application for future restoration
147
	 *
148
	 * Reimplemented to add action/action_id from content set by server
149
	 * when eg. viewing infologs linked to contacts.
150
	 *
151
	 * @return {object} Application specific map representing the current state
152
	 */
153
	getState: function()
154
	{
155
		// call parent
156
		var state = this._super.apply(this, arguments);
157
		var nm = {};
158
159
		// Get index etemplate
160
		var et2 = etemplate2.getById('infolog-index');
161
		if(et2)
162
		{
163
			var content = et2.widgetContainer.getArrayMgr('content');
164
			nm = content && content.data && content.data.nm ? content.data.nm: {};
165
		}
166
167
		state.action = nm.action || null;
168
		state.action_id = nm.action_id || null;
169
170
		return state;
171
	},
172
173
	/**
174
	 * Set the application's state to the given state.
175
	 *
176
	 * Reimplemented to also reset action/action_id.
177
	 *
178
	 * @param {{name: string, state: object}|string} state Object (or JSON string) for a state.
179
	 *	Only state is required, and its contents are application specific.
180
	 *
181
	 * @return {boolean} false - Returns false to stop event propagation
182
	 */
183
	setState: function(state)
184
	{
185
		// as we have to set state.state.action, we have to set all other
186
		// for "No filter" favorite to work as expected
187
		var to_set = {col_filter: null, filter: '', filter2: '', cat_id: '', search: '', action: null};
188
		if (typeof state.state == 'undefined') state.state = {};
189
		for(var name in to_set)
190
		{
191
			if (typeof state.state[name] == 'undefined') state.state[name] = to_set[name];
192
		}
193
		return this._super.apply(this, arguments);
194
	},
195
196
	/**
197
	 * Enable or disable the date filter
198
	 *
199
	 * If the filter is set to something that needs dates, we enable the
200
	 * header_left template.  Otherwise, it is disabled.
201
	 */
202
	filter_change: function()
203
	{
204
		var filter = this.et2.getWidgetById('filter');
205
		var nm = this.et2.getWidgetById('nm');
206
		var dates = this.et2.getWidgetById('infolog.index.dates');
207
		if(nm && filter)
208
		{
209
			switch(filter.getValue())
210
			{
211
				case 'bydate':
212
				case 'duedate':
213
214
					if (filter && dates)
215
					{
216
						dates.set_disabled(false);
217
						window.setTimeout(function() {
218
							jQuery(dates.getWidgetById('startdate').getDOMNode()).find('input').focus();
219
						},0);
220
					}
221
					break;
222
				default:
223
					if (dates)
224
					{
225
						dates.set_disabled(true);
226
					}
227
					break;
228
			}
229
		}
230
	},
231
232
	/**
233
	 * show or hide the details of rows by selecting the filter2 option
234
	 * either 'all' for details or 'no_description' for no details
235
	 *
236
	 * @param {Event} event Change event
237
	 * @param {et2_nextmatch} nm The nextmatch widget that owns the filter
238
	 */
239
	filter2_change: function(event, nm)
240
	{
241
		var filter2 = nm.getWidgetById('filter2');
242
243
		if (nm && filter2)
244
		{
245
			// Show / hide descriptions
246
			this.show_details(filter2.get_value() === 'all', nm.getDOMNode(nm));
247
		}
248
249
		// Only change columns for a real user event, to avoid interfering with
250
		// favorites
251
		if (nm && filter2 && !nm.update_in_progress)
252
		{
253
			// Store selection as implicit preference
254
			egw.set_preference('infolog', nm.options.settings.columnselection_pref.replace('-details','')+'-details-pref', filter2.value);
255
256
			// Change preference location - widget is nextmatch
257
			nm.options.settings.columnselection_pref = nm.options.settings.columnselection_pref.replace('-details','') + (filter2.value == 'all' ? '-details' :'');
258
259
			// Load new preferences
260
			var colData = nm.columns.slice();
261
			for(var i = 0; i < nm.columns.length; i++) colData[i].visible=false;
262
263
			if(egw.preference(nm.options.settings.columnselection_pref,'infolog'))
264
			{
265
				nm.set_columns(egw.preference(nm.options.settings.columnselection_pref,'infolog').split(','));
266
			}
267
			nm._applyUserPreferences(nm.columns, colData);
268
269
			// Now apply them to columns
270
			for(var i = 0; i < colData.length; i++)
271
			{
272
				nm.dataview.getColumnMgr().columns[i].set_width(colData[i].width);
273
				nm.dataview.getColumnMgr().columns[i].set_visibility(colData[i].visible);
274
			}
275
			nm.dataview.getColumnMgr().updated = true;
276
277
			// Update page - set update_in_progress to true to avoid triggering
278
			// the change handler and looping if the user has a custom field
279
			// column change
280
			var in_progress = nm.update_in_progress;
281
			nm.update_in_progress = true;
282
			nm.dataview.updateColumns();
283
			nm.update_in_progress = in_progress;
284
		}
285
		return false;
286
	},
287
288
	/**
289
	 * Show or hide details by changing the CSS class
290
	 *
291
	 * @param {boolean} show
292
	 * @param {DOMNode} dom_node
293
	 */
294
	show_details: function(show, dom_node)
295
	{
296
		// Show / hide descriptions
297
        egw.css((dom_node && dom_node.id ? "#"+dom_node.id+' ' : '') + ".et2_box.infoDes","display:" + (show ? "block;" : "none;"));
298
		if (egwIsMobile())
299
		{
300
			var $select = jQuery('.infoDetails');
301
			(show)? $select.each(function(i,e){jQuery(e).hide();}): $select.each(function(i,e){jQuery(e).show();});
302
		}
303
	},
304
305
	confirm_delete_2: function (_action, _senders)
306
	{
307
		var children = false;
308
		var child_button = jQuery('#delete_sub').get(0) || jQuery('[id*="delete_sub"]').get(0);
309
		if(child_button)
310
		{
311
			for(var i = 0; i < _senders.length; i++)
312
			{
313
				if (jQuery(_senders[i].iface.node).hasClass('infolog_rowHasSubs'))
314
				{
315
					children = true;
316
					break;
317
				}
318
			}
319
			child_button.style.display = children ? 'block' : 'none';
320
		}
321
		var callbackDeleteDialog = function (button_id)
322
		{
323
			if (button_id == et2_dialog.YES_BUTTON )
324
			{
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
325
326
			}
327
		};
328
		et2_dialog.show_dialog(callbackDeleteDialog, this.egw.lang("Do you really want to DELETE this Rule"),this.egw.lang("Delete"), {},et2_dialog.BUTTONS_YES_NO_CANCEL, et2_dialog.WARNING_MESSAGE);
329
	},
330
331
	/**
332
	 * Confirm delete
333
	 * If entry has children, asks if you want to delete children too
334
	 *
335
	 *@param _action
336
	 *@param _senders
337
	 */
338
	confirm_delete: function(_action, _senders)
339
	{
340
		var children = false;
341
		var child_button = jQuery('#delete_sub').get(0) || jQuery('[id*="delete_sub"]').get(0);
342
		if(child_button)
343
		{
344
			for(var i = 0; i < _senders.length; i++)
345
			{
346
				if (jQuery(_senders[i].iface.getDOMNode()).hasClass('infolog_rowHasSubs'))
347
				{
348
					children = true;
349
					break;
350
				}
351
			}
352
			child_button.style.display = children ? 'block' : 'none';
353
		}
354
		nm_open_popup(_action, _senders);
355
	},
356
357
	/**
358
	 * Add email from addressbook
359
	 *
360
	 * @param ab_id
361
	 * @param info_cc
362
	 */
363
	add_email_from_ab: function(ab_id,info_cc)
364
	{
365
		var ab = document.getElementById(ab_id);
366
367
		if (!ab || !ab.value)
368
		{
369
			jQuery("tr.hiddenRow").css("display", "table-row");
370
		}
371
		else
372
		{
373
			var cc = document.getElementById(info_cc);
374
375
			for(var i=0; i < ab.options.length && ab.options[i].value != ab.value; ++i) ;
0 ignored issues
show
introduced by
The for loop does not have a body. Maybe you have misplaced a semicolon. If you do wish to have a loop without a body, use an empty body {}.
Loading history...
376
377
			if (i < ab.options.length)
378
			{
379
				cc.value += (cc.value?', ':'')+ab.options[i].text.replace(/^.* <(.*)>$/,'$1');
380
				ab.value = '';
381
				ab.onchange();
382
				jQuery("tr.hiddenRow").css("display", "none");
383
			}
384
		}
385
		return false;
386
	},
387
388
	/**
389
	* If one of info_status, info_percent or info_datecompleted changed --> set others to reasonable values
390
	*
391
	* @param {string} changed_id id of changed element
392
	* @param {string} status_id
393
	* @param {string} percent_id
394
	* @param {string} datecompleted_id
395
	*/
396
	status_changed: function(changed_id, status_id, percent_id, datecompleted_id)
397
	{
398
		// Make sure this doesn't get executed while template is loading
399
		if(this.et2 == null || this.et2.getInstanceManager() == null) return;
400
401
		var status = document.getElementById(status_id);
402
		var percent = document.getElementById(percent_id);
403
		var datecompleted = document.getElementById(datecompleted_id+'[str]');
404
		if(!datecompleted)
405
		{
406
			datecompleted = jQuery('#'+datecompleted_id +' input').get(0);
407
		}
408
		var completed;
409
410
		switch(changed_id)
0 ignored issues
show
Coding Style introduced by
As per coding-style, switch statements should have a default case.
Loading history...
411
		{
412
			case status_id:
413
				completed = status.value == 'done' || status.value == 'billed';
414
				if (completed || status.value == 'not-started' ||
415
					(status.value == 'ongoing') != (percent.value > 0 && percent.value < 100))
416
				{
417
					if(completed)
418
					{
419
						percent.value = 100;
420
					}
421
					else if (status.value == 'not-started')
422
					{
423
						percent.value = 0;
424
					}
425
					else if (!completed && (percent.value == 0 || percent.value == 100))
426
					{
427
						percent.value = 10;
428
					}
429
				}
430
				break;
431
432
			case percent_id:
433
				completed = percent.value == 100;
434
				if (completed != (status.value == 'done' || status.value == 'billed') ||
435
					(status.value == 'not-started') != (percent.value == 0))
436
				{
437
					status.value = percent.value == 0 ? (jQuery('[value="not-started"]',status).length ? 'not-started':'ongoing') : (percent.value == 100 ? 'done' : 'ongoing');
438
				}
439
				break;
440
441
			case datecompleted_id+'[str]':
442
			case datecompleted_id:
443
				completed = datecompleted.value != '';
444
				if (completed != (status.value == 'done' || status.value == 'billed'))
445
				{
446
					status.value = completed ? 'done' : 'not-started';
447
				}
448
				if (completed != (percent.value == 100))
449
				{
450
					percent.value = completed ? 100 : 0;
451
				}
452
				break;
453
		}
454
		if (!completed && datecompleted && datecompleted.value != '')
455
		{
456
			datecompleted.value = '';
457
		}
458
		else if (completed && datecompleted && datecompleted.value == '')
459
		{
460
			// todo: set current date in correct format
461
		}
462
	},
463
464
	/**
465
	 * handle "print" action from "Actions" selectbox in edit infolog window.
466
	 * check if the template is dirty then submit the template otherwise just open new window as print.
467
	 *
468
	 */
469
	edit_actions: function()
470
	{
471
		var widget = this.et2.getWidgetById('action');
472
		var template = this.et2._inst;
473
		if (template)
474
		{
475
			var id = template.widgetContainer.getArrayMgr('content').data['info_id'];
476
		}
477
		if (widget)
478
		{
479
			switch (widget.get_value())
480
			{
481
				case 'print':
482
					if (template.isDirty())
483
					{
484
						template.submit();
485
					}
486
					egw_open(id,'infolog','edit',{print:1});
0 ignored issues
show
Bug introduced by
The variable id does not seem to be initialized in case template on line 473 is false. Are you sure the function egw_open handles undefined variables?
Loading history...
487
					break;
488
				default:
489
					template.submit();
490
			}
491
		}
492
	},
493
494
	/**
495
	 * Open infolog entry for printing
496
	 *
497
	 * @param {aciton object} _action
498
	 * @param {object} _selected
499
	 */
500
	infolog_menu_print: function(_action, _selected)
501
	{
502
		var id = _selected[0].id.replace(/^infolog::/g,'');
503
		egw_open(id,'infolog','edit',{print:1});
504
	},
505
506
	/**
507
	 * Trigger print() onload window
508
	 */
509
	infolog_print_preview_onload: function ()
510
	{
511
		var that = this;
512
		jQuery('#infolog-edit-print').bind('load',function(){
513
			var isLoadingCompleted = true;
514
			jQuery('#infolog-edit-print').bind("DOMSubtreeModified",function(event){
515
					isLoadingCompleted = false;
516
					jQuery('#infolog-edit-print').unbind("DOMSubtreeModified");
517
			});
518
			setTimeout(function() {
519
				isLoadingCompleted = false;
520
			}, 1000);
521
			var interval = setInterval(function(){
522
				if (!isLoadingCompleted)
523
				{
524
					clearInterval(interval);
525
					that.infolog_print_preview();
526
				}
527
			}, 100);
528
		});
529
	},
530
531
	/**
532
	 * Trigger print() function to print the current window
533
	 */
534
	infolog_print_preview: function()
535
	{
536
		this.egw.message(this.egw.lang('Printing...'));
537
		this.egw.window.print();
538
	},
539
540
	/**
541
	 *
542
	 */
543
	add_link_sidemenu: function()
544
	{
545
		egw.open('','infolog','add');
546
	},
547
548
	/**
549
	 * Wrapper so add -> New actions in the context menu can pass current
550
	 * filter values into new edit dialog
551
	 *
552
	 * @see add_with_extras
553
	 *
554
	 * @param {egwAction} action
555
	 * @param {egwActionObject[]} selected
556
	 */
557
	add_action_handler: function(action, selected)
558
	{
559
		var nm = action.getManager().data.nextmatch || false;
560
		if(nm)
561
		{
562
			this.add_with_extras(nm,action.id,
563
				nm.getArrayMgr('content').getEntry('action'),
564
				nm.getArrayMgr('content').getEntry('action_id')
565
			);
566
		}
567
	},
568
569
	/**
570
	 * Opens a new edit dialog with some extra url parameters pulled from
571
	 * standard locations.  Done with a function instead of hardcoding so
572
	 * the values can be updated if user changes them in UI.
573
	 *
574
	 * @param {et2_widget} widget Originating/calling widget
575
	 * @param _type string Type of infolog entry
576
	 * @param _action string Special action for new infolog entry
577
	 * @param _action_id string ID for special action
578
	 */
579
	add_with_extras: function(widget,_type, _action, _action_id)
580
	{
581
		// We use widget.getRoot() instead of this.et2 for the case when the
582
		// addressbook tab is viewing a contact + infolog list, there's 2 infolog
583
		// etemplates
584
		var nm = widget.getRoot().getWidgetById('nm');
585
		var nm_value = nm.getValue() || {};
586
587
		// It's important that all these keys are here, they override the link
588
		// registry.
589
		var action_id = nm_value.action_id ? nm_value.action_id : (_action_id != '0' ? _action_id : "") || "";
590
		if(typeof action_id == "object" && typeof action_id.length == "undefined")
591
		{
592
			// Need a real array here
593
			action_id = jQuery.map(action_id,function(val) {return val;});
594
		}
595
596
		// No action?  Try the linked filter, in case it's set
597
		if(!_action && !_action_id)
598
		{
599
			if(nm_value.col_filter && nm_value.col_filter.linked)
600
			{
601
				var split = nm_value.col_filter.linked.split(':') || '';
602
				_action = split[0] || '';
603
				action_id = split[1] || '';
604
			}
605
		}
606
		var extras = {
607
			type: _type || nm_value.col_filter.info_type || "task",
608
			cat_id: nm_value.cat_id || "",
609
			action: nm_value.action || _action || "",
610
			// egw_link can handle arrays, but server is expecting CSV
611
			action_id: typeof action_id.join != "undefined" ? action_id.join(',') : action_id
612
		};
613
		egw.open('','infolog','add',extras);
614
	},
615
616
	/**
617
	 * Get title in order to set it as document title
618
	 * @returns {string}
619
	 */
620
	getWindowTitle: function()
621
	{
622
		var widget = this.et2.getWidgetById('info_subject');
623
		if(widget) return widget.options.value;
624
	},
625
626
	/**
627
	 * View parent entry with all children
628
	 *
629
	 * @param {aciton object} _action
630
	 * @param {object} _selected
631
	 */
632
	view_parent: function(_action, _selected)
633
	{
634
		var data = egw.dataGetUIDdata(_selected[0].id);
635
		if (data && data.data && data.data.info_id_parent)
636
		{
637
			egw.link_handler(egw.link('/index.php', {
638
				menuaction: "infolog.infolog_ui.index",
639
				action: "sp",
640
				action_id: data.data.info_id_parent,
641
				ajax: "true"
642
			}), "infolog");
643
		}
644
	},
645
646
	/**
647
	 * View a list of timesheets for the linked infolog entry
648
	 *
649
	 * Only one infolog entry at a time is allowed, we just pick the first one
650
	 *
651
	 * @param {egwAction} _action
652
	 * @param {egwActionObject[]} _selected
653
	 */
654
	timesheet_list: function(_action, _selected)
655
	{
656
		var extras = {
657
			link_app: 'infolog',
658
			link_id: false
659
		};
660
		for(var i = 0; i < _selected.length; i++)
0 ignored issues
show
introduced by
This code is unreachable and can thus be removed without consequences.
Loading history...
Bug introduced by
The variable i seems to be never initialized.
Loading history...
661
		{
662
			// Remove UID prefix for just contact_id
663
			var ids = _selected[i].id.split('::');
664
			ids.shift();
665
			ids = ids.join('::');
666
667
			extras.link_id = ids;
668
			break;
669
		}
670
671
		egw.open("","timesheet","list", extras, 'timesheet');
672
	},
673
674
	/**
675
	 * Go to parent entry
676
	 *
677
	 * @param {aciton object} _action
678
	 * @param {object} _selected
679
	 */
680
	has_parent: function(_action, _selected)
681
	{
682
		var data = egw.dataGetUIDdata(_selected[0].id);
683
684
		return data && data.data && data.data.info_id_parent > 0;
685
	},
686
687
	/**
688
	 * Submit template if widget has a value
689
	 *
690
	 * Used for project-selection to update pricelist items from server
691
	 *
692
	 * @param {DOMNode} _node
693
	 * @param {et2_widget} _widget
694
	 */
695
	submit_if_not_empty: function(_node, _widget)
696
	{
697
		if (_widget.get_value()) this.et2._inst.submit();
698
	},
699
700
	/**
701
	 * Toggle encryption
702
	 *
703
	 * @param {jQuery.Event} _event
704
	 * @param {et2_button} _widget
705
	 * @param {DOMNode} _node
706
	 */
707
	toggleEncrypt: function(_event, _widget, _node)
708
	{
709
		if (!this.egw.user('apps').stylite)
710
		{
711
			this.egw.message(this.egw.lang('InfoLog encryption requires EPL Subscription')+': <a href="http://www.egroupware.org/EPL">www.egroupware.org/EPL</a>');
712
			return;
713
		}
714
		this._get_stylite(function() {app.stylite.toggleEncrypt.call(app.stylite,_event,_widget,_node);});
715
	},
716
717
	/**
718
	 * Make sure stylite javascript is loaded, and call the given callback when it is
719
	 *
720
	 * @param {function} callback
721
	 * @param {object} attrs
722
	 *
723
	 */
724
	_get_stylite: function(callback,attrs)
725
	{
726
		// use app object from etemplate2, which might be private and not just window.app
727
		var app = this.et2.getInstanceManager().app_obj;
728
729
		if (!app.stylite)
730
		{
731
			var self = this;
732
			egw_LAB.script('stylite/js/infolog-encryption.js?'+this.et2.getArrayMgr('content').data.encryption_ts).wait(function()
733
			{
734
				app.stylite = new app.classes.stylite;
735
				app.stylite.et2 = self.et2;
736
				if(callback)
737
				{
738
					callback.apply(app.stylite,attrs);
739
				}
740
			});
741
		}
742
		else
743
		{
744
			app.stylite.et2 = this.et2;
745
			callback.apply(app.stylite,attrs);
746
		}
747
	},
748
749
	/**
750
	 * OnChange callback for responsible
751
	 *
752
	 * @param {jQuery.Event} _event
753
	 * @param {et2_widget} _widget
754
	 */
755
	onchangeResponsible: function(_event, _widget)
756
	{
757
		if (app.stylite && app.stylite.onchangeResponsible)
758
		{
759
			app.stylite.onchangeResponsible.call(app.stylite, _event, _widget);
760
		}
761
	},
762
763
	/**
764
	 * Action handler for context menu change responsible action
765
	 *
766
	 * We populate the dialog with the current value.
767
	 *
768
	 * @param {egwAction} _action
769
	 * @param {egwActionObject[]} _selected
770
	 */
771
	change_responsible: function(_action, _selected)
772
	{
773
		var et2 = _selected[0].manager.data.nextmatch.getInstanceManager();
774
		var responsible = et2.widgetContainer.getWidgetById('responsible');
775
		if(responsible)
776
		{
777
			responsible.set_value([]);
778
			et2.widgetContainer.getWidgetById('responsible_action[title]').set_value('');
779
			et2.widgetContainer.getWidgetById('responsible_action[title]').set_class('');
780
			et2.widgetContainer.getWidgetById('responsible_action[ok]').set_disabled(_selected.length !== 1);
781
			et2.widgetContainer.getWidgetById('responsible_action[add]').set_disabled(_selected.length === 1)
782
			et2.widgetContainer.getWidgetById('responsible_action[delete]').set_disabled(_selected.length === 1)
783
		}
784
785
		if(_selected.length === 1)
786
		{
787
			var data = egw.dataGetUIDdata(_selected[0].id);
788
789
			if(responsible && data && data.data)
790
			{
791
				et2.widgetContainer.getWidgetById('responsible_action[title]').set_value(data.data.info_subject);
792
				et2.widgetContainer.getWidgetById('responsible_action[title]').set_class(data.data.sub_class)
793
				responsible.set_value(data.data.info_responsible);
794
			}
795
		}
796
797
		nm_open_popup(_action, _selected);
798
	},
799
800
	/**
801
	 * Handle encrypted info_desc for print purpose
802
	 * and triggers print action after decryption
803
	 *
804
	 * @param {Keyring} _keyring Mailvelope keyring to use
805
	 */
806
	printEncrypt: function (_keyring)
807
	{
808
		//this.mailvelopeAvailable(this.toggleEncrypt);
809
		var info_desc = this.et2.getWidgetById('info_des');
810
811
		var self = this;
812
		mailvelope.createDisplayContainer('#infolog-edit-print_info_des', info_desc.value, _keyring).then(function(_container)
813
		{
814
			var $info_des_dom = jQuery(self.et2.getWidgetById('info_des').getDOMNode());
815
//			$info_des_dom.children('iframe').height($info_des_dom.height());
816
			$info_des_dom.children('span').hide();
817
			//Trigger print action
818
			self.infolog_print_preview();
819
		},
820
		function(_err)
821
		{
822
			self.egw.message(_err, 'error');
823
		});
824
	}
825
826
});
827